//
//  IMTHTTPSessionManager.m
//  INMOTION
//
//  Created by Kyle on 3/5/15.
//  Copyright (c) 2015 Inmotion. All rights reserved.
//

#import "IMTHTTPSessionManager.h"
#import "AFNetworkActivityIndicatorManager.h"
#import "KSJSON.h"
#import "KSLanguageManager.h"
#import "KSCrypto.h"
#import "SVProgressHUD.h"
#import "MBProgressHUD+KS.h"
#import "UserModel.h"

NSString * const IMTHTTPSessionErrorDomain = @"IMTHTTPSessionErrorDomain";
NSString * const kIMTReleaseBaseUrl = @"https://app.imscv.com"; // 测试环境 https://app.t.imscv.com  开发环境 https://app.imscv.com
NSString * const kIMTDevelopmentBaseUrl = @"http://lbstcp.imscv.com"; //@"http://tapp.imscv.com:82";
NSString * const IMTUseDevelopmentRequestUrlKey = @"IMTUseDevelopmentRequestUrlKey";

const NSInteger IMTHTTPSessionManagerRequestCancelCode = -999;
const NSInteger IMTHTTPSessionManagerAuthorizationFailedCode = 3000;

typedef void (^IMTHTTPSessionSuccessBlock)(NSURLSessionDataTask *task, id responseObject);


static IMTHTTPSessionManager *_sharedInstance;

@interface IMTHTTPSessionManager ()

@end

@implementation IMTHTTPSessionManager

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[IMTHTTPSessionManager alloc] initWithBaseURL:nil];
        _sharedInstance.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
        _sharedInstance.responseSerializer.acceptableContentTypes = [_sharedInstance.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
        [[NSNotificationCenter defaultCenter] addObserver:_sharedInstance selector:@selector(cancelAllTasks) name:@"kCancelAFTask" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:_sharedInstance selector:@selector(userDidLogOut:) name:@"IMTLogoutSuccessNotification" object:nil];
        
        NSString *userAgent = nil;
        #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
            // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
            userAgent = [NSString stringWithFormat:@"%@/%@ %@ iOS%@ InmotionApi/2", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion]];
        #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
            userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
        #endif
        [_sharedInstance.requestSerializer setValue:userAgent forHTTPHeaderField:@"User-Agent"];

    });
    return _sharedInstance;
}

- (void)cancelAllTasks {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"kCancelASIRequest" object:nil];
    [self.tasks enumerateObjectsUsingBlock:^(NSURLSessionTask *task, NSUInteger idx, BOOL *stop) {
        [task cancel];
    }];
}

- (void)showAlertView {
    if (!self.reloginAlertShowing) {
        UIAlertController *ac = [UIAlertController alertControllerWithTitle:IMTLocalizedString(@"WarmTips", nil) message:IMTLocalizedString(@"ReLoginTips", nil) preferredStyle:(UIAlertControllerStyleAlert)];
        UIAlertAction *cancle = [UIAlertAction actionWithTitle:IMTLocalizedString(@"NormalCancel", nil) style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
            self.reloginAlertShowing = NO;
            [[NSNotificationCenter defaultCenter] postNotificationName:@"IMTLogoutSuccessNotification" object:nil];
        }];
        [ac addAction:cancle];
        [[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:ac animated:YES completion:nil];
        self.reloginAlertShowing = YES;
    }
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Notification

- (void)userDidLogOut:(NSNotification *)notification {
    [self.tasks enumerateObjectsUsingBlock:^(NSURLSessionTask *task, NSUInteger idx, BOOL *stop) {
        [task cancel];
    }];
    [self configUrl];
}

#pragma mark - URL

- (void)configUrl {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults boolForKey:IMTUseDevelopmentRequestUrlKey]) {
        self.baseUrl = kIMTDevelopmentBaseUrl;
    } else {
        self.baseUrl = kIMTReleaseBaseUrl;
    }

#ifndef __OPTIMIZE__
    self.baseUrl = kIMTReleaseBaseUrl;
#else
    self.baseUrl = kIMTReleaseBaseUrl;
#endif
}

- (void)setBaseUrl:(NSString *)baseUrl {
    _baseUrl = baseUrl;
    
    if ([baseUrl isEqualToString:kIMTReleaseBaseUrl]) {
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:IMTUseDevelopmentRequestUrlKey];
    } else {
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:IMTUseDevelopmentRequestUrlKey];
    }
    
    NSString *language = [[KSLanguageManager sharedInstance] currentLanguage];
    self.languageShortString = kIMTEnglishPrefix;
    if ([language hasPrefix:kIMTSimplifiedChinesePrefix]) {
        self.languageShortString = @"cn"; /// kIMTSimplifiedChinesePrefix - > 替换成了“cn”
    } else if ([language hasPrefix:@"zh-HK"] || [language hasPrefix:kIMTTraditionnalChinesePrefix]) {
        self.languageShortString = @"hk";
    } else if ([language isEqualToString:kIMTKoreanPrefix]) {
        self.languageShortString = kIMTKoreanPrefix;
    } else if ([language isEqualToString:kIMTRussianPrefix]) {
        self.languageShortString = kIMTRussianPrefix;
    }
} 

- (NSString *)memberUrl {
    return [self urlWithApi:@"member"];
}

- (NSString *)apiUrl {
    return [self urlWithApi:@"api"];
}

- (NSString *)lbsUrl {
    return [self urlWithApi:@"lbs"];
}

- (NSString *)urlWithApi:(NSString *)api {
    return [NSString stringWithFormat:@"%@/%@/%@/", self.baseUrl, api, self.languageShortString];
}

#pragma mark - Parameters
- (NSDictionary *)wrappedParametersWithParameters:(NSDictionary *)parameters {
    NSDate *date = [NSDate date];
    NSString *token = [NSString stringWithFormat:@"%@@%f", [UserModel getToken], [date timeIntervalSince1970]];
    NSMutableDictionary *wrappedParameters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[KSCrypto aes128Encrypt:token], @"token", nil];
    if (parameters) {
        [wrappedParameters setObject:[parameters ks_JSONString] forKey:@"data"];
    }
    return wrappedParameters;
}

#pragma mark - POST
- (NSURLSessionDataTask *)ks_POST:(NSString *)URLString
                              api:(NSString *)api
                       parameters:(id)parameters
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
    
    NSString *url = [NSString stringWithFormat:@"%@%@", [self urlWithApi:api], URLString];
    NSString *sysUA = self.requestSerializer.HTTPRequestHeaders[@"User-Agent"];
    NSDictionary *wrappedParameters = [self wrappedParametersWithParameters:parameters];
    NSLog(@"请求地址---------------User-Agent:%@  url:%@ params:\n%@", sysUA, url, wrappedParameters);
    NSURLSessionDataTask *task = [super POST:url parameters:wrappedParameters success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"请求成功--------------- url:%@ response:\n%@", url, responseObject);
        [self handleResponseWithTask:task
                      responseObject:responseObject
                             success:success
                             failure:failure];
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"请求失败---------------URL：%@  error： %@",url,[error description]);
        if (![URLString isEqualToString:@"getNearbyPerson"]) {
            [self handleFailureWithTask:task
                                  error:error
                                failure:failure];
        }
    }];

    return task;
}

- (NSURLSessionDataTask *)gy_POST:(NSString *)URLString
                       parameters:(id)parameters
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSDate *date = [NSDate date];
    NSString *token = [NSString stringWithFormat:@"%@@%f", @"5636ec65d14990f21505062e288d4a33", [date timeIntervalSince1970]];
    NSMutableDictionary *wrappedParameters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[KSCrypto aes128Encrypt:token],@"token", nil];
    if (parameters) {
        [wrappedParameters setObject:[parameters ks_JSONString] forKey:@"data"];
    }
    
    NSString *url = [NSString stringWithFormat:@"http://lkapi.imscv.com/api/cn/%@", URLString];
    NSLog(@"url:%@ params:\n%@", url, wrappedParameters);
    NSURLSessionDataTask *task = [super POST:url parameters:wrappedParameters success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"url:%@ response:\n%@", url, responseObject);
        [self handleResponseWithTask:task
                      responseObject:responseObject
                             success:success
                             failure:failure];
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"%@",[error description]);
        [self handleFailureWithTask:task
                              error:error
                            failure:failure];
    }];
    
    return task;
}

- (NSURLSessionDataTask *)ks_POST:(NSString *)URLString
                       parameters:(id)parameters
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
    return [self ks_POST:URLString api:@"api" parameters:parameters success:success failure:failure];
}

- (NSURLSessionDataTask *)lbs_POST:(NSString *)URLString
                        parameters:(id)parameters
                           success:(void (^)(NSURLSessionDataTask *, id))success
                           failure:(void (^)(NSURLSessionDataTask *, NSError *))failure {
    return [self ks_POST:URLString api:@"lbs" parameters:parameters success:success failure:failure];
}

- (NSURLSessionDataTask *)ks_POST:(NSString *)URLString
                              api:(NSString *)api
                       parameters:(id)parameters
        constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> formData))block
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {

    NSString *url = [NSString stringWithFormat:@"%@%@", [self urlWithApi:api], URLString];
    NSDictionary *wrappedParameters = [self wrappedParametersWithParameters:parameters];
    NSLog(@"请求================url:%@ ======= params:%@",url,wrappedParameters);
    NSURLSessionDataTask *task = [super POST:url parameters:wrappedParameters constructingBodyWithBlock:block success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"url:%@\nresponse:%@", URLString, responseObject);
        [self handleResponseWithTask:task
                      responseObject:responseObject
                             success:success
                             failure:failure];
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"%@",[error description]);
        [self handleFailureWithTask:task
                              error:error
                            failure:failure];
    }];
    
    return task;
}

- (NSURLSessionDataTask *)ks_POST:(NSString *)URLString
                       parameters:(id)parameters
        constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> formData))block
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{
    return [self ks_POST:URLString api:@"api" parameters:parameters constructingBodyWithBlock:block success:success failure:failure];
}

- (NSURLSessionDataTask *)lbs_POST:(NSString *)URLString
                       parameters:(id)parameters
        constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> formData))block
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{
    return [self ks_POST:URLString api:@"lbs" parameters:parameters constructingBodyWithBlock:block success:success failure:failure];
}

- (NSURLSessionUploadTask *)ks_uploadTaskWithStreamedRequest:(NSURLRequest *)request progress:(NSProgress *__autoreleasing *)progress completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {
    return [super uploadTaskWithStreamedRequest:request progress:progress completionHandler:completionHandler];
}

#pragma mark - Response

- (void)handleResponseWithTask:(NSURLSessionDataTask *)task
                responseObject:(id)responseObject
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSString *codeString = [NSString stringWithFormat:@"%@", [responseObject objectForKey:@"code"]];
    NSInteger code = 0;
    NSString *codeType = @"E";
    if (codeString.length > 1) {
        codeType = [codeString substringToIndex:1];
        code = [[codeString substringFromIndex:1] integerValue];
    }
    if ([codeType isEqualToString:@"N"]) {
        if (success) {
            success(task, responseObject);
        }
    } else if ([codeType isEqualToString:@"E"] || [codeType isEqualToString:@"W"]) {
        NSError *error = [NSError errorWithDomain:IMTHTTPSessionErrorDomain
                                             code:code
                                         userInfo:@{NSLocalizedDescriptionKey:[responseObject objectForKey:@"message"]}];
        if (failure) {
            failure(task, error);
        } else {
#ifdef INDIVIDUAL_APP
            [MBProgressHUD showText:error.localizedDescription inView:nil];
#else
            [SVProgressHUD showErrorWithStatus:error.localizedDescription];
#endif
        }
        
        //权限验证失败
        if (code == IMTHTTPSessionManagerAuthorizationFailedCode) {
            [self cancelAllTasks];
            [self showAlertView];
        }
    } else {
        NSError *error = [NSError errorWithDomain:IMTHTTPSessionErrorDomain
                                             code:code
                                         userInfo:@{NSLocalizedDescriptionKey:IMTLocalizedString(@"ServerError", nil)}];
        if (failure) {
            failure(task, error);
        } else {
#ifdef INDIVIDUAL_APP
            [MBProgressHUD showText:error.localizedDescription inView:nil];
#else
            [SVProgressHUD showErrorWithStatus:error.localizedDescription];
#endif
        }
    }
}

- (void)handleFailureWithTask:(NSURLSessionDataTask *)task
                        error:(NSError *)error
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
    // 不是取消的请求
    if (error.code != IMTHTTPSessionManagerRequestCancelCode) {
        NSError *localizedError = [NSError errorWithDomain:error.domain
                                                      code:error.code
                                                  userInfo:@{NSLocalizedDescriptionKey:IMTLocalizedString(@"NetworkError", nil)}];
        if (failure) {
            failure(task, localizedError);
        } else {
#ifdef INDIVIDUAL_APP
            [MBProgressHUD showText:error.localizedDescription inView:nil];
#else
            [SVProgressHUD showErrorWithStatus:error.localizedDescription];
#endif
        }
    }
}

@end
